De vuxna på skolan reagerar om de får reda på att någon har varit elak mot en elev
q10
Jag vet vem på skolan jag kan vända mig till om någon är elak mot mig
q14
Jag upplever att elevrådet har möjlighet att vara delaktigt i beslut
q15
Jag känner till FN:s barnkonvention och mina rättigheter enligt den
q27
Jag trivs på fritidshemmet
q28
Jag känner mig trygg på fritidshemmet
q29
Jag får vara med och påverka vad vi gör på fritidshemmet
q30
Det jag lär mig på fritidshemmet hjälper mig i skolarbetet
q32
Jag lär och utvecklar mig på modersmålsundervisningen
q33
Jag får hjälp av min modersmålslärare när jag behöver den
q34
Jag kan koncentrera mig på modersmålsundervisningen
Ovanstående frågor har fyra svarskategorier, där bara ändpunkterna har etiketter (Instämmer helt - Instämmer inte alls), samt alternativet “Vet ej”.
Fråga 11-12 kan besvaras med Ja/Nej.
q11: Har du varit utsatt för kränkning på din skola i år?
q12: Har du varit utsatt för upprepade kränkningar på din skola i år?
Code
itemlabels %>%slice(c(27:30,32:34)) %>%kbl_rise()
itemnr
item
q27
Jag trivs på fritidshemmet
q28
Jag känner mig trygg på fritidshemmet
q29
Jag får vara med och påverka vad vi gör på fritidshemmet
q30
Det jag lär mig på fritidshemmet hjälper mig i skolarbetet
q32
Jag lär och utvecklar mig på modersmålsundervisningen
q33
Jag får hjälp av min modersmålslärare när jag behöver den
q34
Jag kan koncentrera mig på modersmålsundervisningen
Fråga 27-30 handlar om fritidshemmet, medan 31-34 handlar om modersmålsundervisning.
Fråga 13 är “Var känner du dig minst trygg på skolan?”, med följande åtta möjliga svarsalternativ:
Code
df %>%distinct(q13) %>%filter(!q13 =="NA") %>%rename(`Var känner du dig minst trygg på skolan?`= q13) %>%kbl_rise()
Var känner du dig minst trygg på skolan?
Jag känner mig trygg överallt på skolan
Korridoren
Omklädningsrummet
Skolgården
Klassrummet
Annat:
Matsalen
Internet/sociala medier
Frågorna 16-22 handlar om de sju diskrimineringsgrunderna, och fråga 23 blir svårtolkad. Ska man svara “Ja” på den om man blivit illa behandlad på grund av något annat än de sju diskrimineringsgrunderna, eller om man inte alls blivit illa behandlad? Vad betyder “Nej” på den frågan?
Fråga 24 och 25 handlar om utsatthet för sexuella trakasserier någon gång under året (oavsett plats) samt om det hänt upprepade gånger på skolan (Ja/nej/vet ej).
Code
itemlabels %>%slice(c(16:23)) %>%kbl_rise()
itemnr
item
q16
Har du känt dig illa/annorlunda behandlad på din skola i år på grund av: - Ditt kön
q17
Har du känt dig illa/annorlunda behandlad på din skola i år på grund av: - Din etniska bakgrund
q18
Har du känt dig illa/annorlunda behandlad på din skola i år på grund av: - Din religion eller trosuppfattning
q19
Har du känt dig illa/annorlunda behandlad på din skola i år på grund av: - Ditt funktionshinder
q20
Har du känt dig illa/annorlunda behandlad på din skola i år på grund av: - Din sexuella läggning
q21
Har du känt dig illa/annorlunda behandlad på din skola i år på grund av: - Din ålder
q22
Har du känt dig illa/annorlunda behandlad på din skola i år på grund av: - Din könsidentitet/ könsuttryck
q23
Har du känt dig illa/annorlunda behandlad på din skola i år på grund av: - Inget av ovanstående
4 Explorativ analys
Vi lägger in fråga 1-12 i en analys för att se om de kan användas tillsammans för att estimera indexvärden. Initialt tittar vi enbart på data från högstadiet.
Fyra items har exakt samma struktur. Det antyder dels att data är “tvättade” redan, och att det rör sig om items som tillkommit/tagits bort vid någon datainsamling.
Låt oss titta på andelen missing data (NA) per år.
Vi kodar om svarskategorierna till siffror inför analysen, och tar bort alla respondenter med missing data. Högre värden = bättre, så gällande fråga 11-12 kodas Ja = 0 och Nej = 1.
Relative cut-off value (highlighted in red) is 0.126, which is 0.2 above the average correlation.
Code
RItargeting(df.index)
Code
RIitemHierarchy(df.index)
Item fit ser bra ut. PCA eigenvalue och residualkorrelationer visar på att flera frågor är väldigt lika varandra. Tydligast är q11 och 12, vilket är förväntat eftersom de handlar om samma sak med olika svårighetsgrad. H
I övrigt är det främst stora residualkorrelationer mellan:
q1 och 2 (trivs i skolan/klassen)
q3 och 4 (koncentrera mig/jobba på lektionerna)
q1 och 6 (trivs och trygg)
q6 och 8 (bra bemött och trygg)
Figuren med faktorladdningar på första kontrastfaktorn visar en möjlig delning i två kluster:
1, 2, 6, 8, 11 och 12 (trivsel, trygghet, frånvaro av kränkningar)
3, 4, 5, 7, 9, 10 (studiero, vuxnas bemötande)
Vi provar att köra två separata analyser.
4.4 Rasch-analys 1 trivsel/trygghet
Code
df.ttf <- df %>%filter(Stadium =="Högstadiet") %>%mutate(across(q1:q10, ~ car::recode(.x,"'Instämmer inte alls'=0; 2=1; 3=2; 'Instämmer helt'=3; 'Vet ej'=NA; '<NA>'=NA", as.factor =FALSE))) %>%mutate(across(q11:q12, ~ car::recode(.x,"'Nej'=0; 'Ja'=1",as.factor =FALSE))) %>%#mutate(q11_12 = q11 + q12) %>% select(q1,q2,q6,q8,q11,q12) %>%na.omit() # itemlabels <- rbind(itemlabels,c("q11_12","Har du varit utsatt för (upprepad) kränkning på din skola i år?"))
Code
RItileplot(df.ttf)
itemnr
item
q1
Jag trivs i skolan
q2
Jag trivs i min klass
q6
Jag känner mig trygg i skolan
q8
Jag blir bra bemött av elever i skolan
q11
Har du varit utsatt för kränkning på din skola i år?
q12
Har du varit utsatt för upprepade kränkningar på din skola i år?
RIitemfitPCM2(df.ttf, samplesize =250, nsamples =32, cpu =8)
OutfitMSQ
InfitMSQ
OutfitZSTD
InfitZSTD
q1
0.683
0.674
-3.207
-3.572
q2
0.906
0.877
-0.961
-1.388
q6
0.676
0.668
-3.533
-3.464
q8
0.931
0.923
-0.777
-0.741
Code
RIpcmPCA(na.omit(df.ttf))
PCA of Rasch model residuals
Eigenvalues
1.52
1.39
1.09
0.01
Code
RIresidcorr(df.ttf, cutoff =0.2)
q1
q2
q6
q8
q1
q2
-0.19
q6
-0.12
-0.39
q8
-0.38
-0.37
-0.19
Note:
Relative cut-off value (highlighted in red) is -0.075, which is 0.2 above the average correlation.
Code
RIloadLoc(df.ttf)
Code
RIitemCats(df.ttf, items ="all", xlims =c(-5,5))
Code
# increase fig-height above as needed, if you have many itemsRItargeting(df.ttf)
Code
RIitemHierarchy(df.ttf)
Code
RIpfit(df.ttf)
Code
RItif(df.ttf)
Dessa items fungerar även om flera har låg item fit, men har låg reliabilitet tillsammans. Vi kan eventuellt använda sammansättningen items för att testa invarians/DIF för frågorna (kommer längre ner i denna analys).
# increase fig-height above as needed, if you have many itemsRItargeting(df.studiero)
Code
RIitemHierarchy(df.studiero)
Code
RIpfit(df.studiero)
Code
RItif(df.studiero)
Item q3 och 4 har en stark residualkorrelation och en av dem behöver tas bort. Vi tar bort q4 eftersom den har något lägre item fit och targeting jämfört med q3.
4.7 Rasch-analys 2 studiero
Code
df.studiero$q4 <-NULL
itemnr
item
q3
Jag kan koncentrera mig på lektionerna
q5
Jag lär mig olika saker på lektionerna
q7
Jag blir bra bemött av vuxna i skolan
q9
De vuxna på skolan reagerar om de får reda på att någon har varit elak mot en elev
q10
Jag vet vem på skolan jag kan vända mig till om någon är elak mot mig
RIitemfitPCM2(df.studiero, samplesize =250, nsamples =32, cpu =8)
OutfitMSQ
InfitMSQ
OutfitZSTD
InfitZSTD
q3
1.004
1.008
0.098
0.427
q5
0.828
0.845
-1.848
-1.778
q7
0.766
0.762
-2.541
-2.871
q9
0.75
0.739
-2.908
-3.42
q10
0.796
0.807
-1.587
-2.094
Code
RIpcmPCA(na.omit(df.studiero))
PCA of Rasch model residuals
Eigenvalues
1.60
1.21
1.14
1.04
0.02
Code
RIresidcorr(df.studiero, cutoff =0.2)
q3
q5
q7
q9
q10
q3
q5
-0.01
q7
-0.29
-0.15
q9
-0.3
-0.26
-0.09
q10
-0.3
-0.29
-0.15
-0.11
Note:
Relative cut-off value (highlighted in red) is 0.005, which is 0.2 above the average correlation.
Code
RIloadLoc(df.studiero)
Code
# increase fig-height above as needed, if you have many itemsRItargeting(df.studiero, xlim =c(-4,5))
Code
RIitemHierarchy(df.studiero)
Code
RIpfit(df.studiero)
Code
RItif(df.studiero)
Det är små skillnader mellan T1 och T2 för q10, men de är inte oordnade. I övrigt ser allt acceptabelt ut, dock med en tydlig takeffekt och låg reliabilitet.
Vi återgår till att titta på samtliga items tillsammans och se om det går att ta fram ett fungerande index.
4.8 Rasch-analys 2 samtliga items
Utifrån vår tidigare analys fanns en del residualkorrelationer att hantera. Vi börjar med att ta bort:
q4 (q3 har bättre targeting)
Samt att vi slår samman q11 och q12, där svaret “Ja” på någon av frågorna blir “Ja” (0) i den nya frågan, och den som svarat “Nej” på båda frågorna blir “Nej” (1). Vi kodar fortfarande konsekvent så att högre värden = bättre/mera önskvärt resultat.
Det är inte optimalt att ställa två ja/nej-frågor med i princip samma innehåll men olika frekvenspåståenden. Om det i stället hade funnits en enda fråga om utsatthet för kränkning med flera frekvenspåståenden hade det fungerat betydligt bättre. Som det är nu uppstår t.ex. situationen där den som blivit utsatt för flera kränkningar kan svara “Nej” på om den blivit utsatt för en kränkning.
Vi börjar med enbart högstadiet. “Annat/Vill ej svara” är en för liten grupp, så den kodas som missing.
Funktionen som gör DIF-analysen fungerar inte korrekt när item q11 är med, eftersom det bara har två svarskategorier. Vi gör därför LRT-analyser som inkluderar q11, och DIF-analyser utan q11. LRT står för Likelihood Ratio Test. Eftersom vi har väldigt stora sampel är det hög sannolikhet att få statistisk signifikans i dessa test, även om skillnaderna är såpass små att de inte är relevanta. Därför behöver vi även undersöka storleken av effekterna på item-nivå.
Values highlighted in red are above the chosen cutoff 0.5 logits. Background color brown and blue indicate the lowest and highest values among the DIF groups.
Väldigt olika utfall mellan de två DIF-metoderna. Men eftersom ingen av dem indikerar DIF för q11q12 väljer vi att gå på analys-metoden som plockar bort q11q12.
De vuxna på skolan reagerar om de får reda på att någon har varit elak mot en elev
q10
Jag vet vem på skolan jag kan vända mig till om någon är elak mot mig
q11q12
Har du varit utsatt för en eller flera kränkningar på din skola i år?
Code
RIdifTableLR(df.dif.tts, dif.tts.årskurs)
Item locations
Standard errors
Item
Åk 7
Åk 8
Åk 9
MaxDiff
All
SE_Åk 7
SE_Åk 8
SE_Åk 9
SE_All
q2
-0.451
-0.687
-0.74
0.289
-0.631
0.156
0.166
0.145
0.089
q3
1.048
0.936
0.854
0.194
0.942
0.125
0.129
0.115
0.071
q5
-0.623
-0.297
-0.513
0.326
-0.492
0.168
0.155
0.145
0.089
q7
-0.537
-0.402
-0.534
0.135
-0.499
0.159
0.152
0.138
0.086
q8
-0.212
-0.709
-0.607
0.497
-0.507
0.149
0.169
0.144
0.088
q9
0.497
0.959
1.226
0.729
0.920
0.124
0.118
0.104
0.065
q10
0.325
0.232
0.423
0.191
0.332
0.130
0.133
0.113
0.072
q11q12
-0.14
-0.095
-0.327
0.232
-0.194
0.074
0.077
0.074
0.043
Note:
Values highlighted in red are above the chosen cutoff 0.5 logits. Background color brown and blue indicate the lowest and highest values among the DIF groups.
Values highlighted in red are above the chosen cutoff 0.5 logits. Background color brown and blue indicate the lowest and highest values among the DIF groups.
df.dif.tts <- df %>%filter(!Stadium =="Förskoleklass") %>%mutate(Kön = car::recode(Kön,"'Annat/Vill ej svara'=NA")) %>%drop_na(Stadium,Kön) %>%mutate(across(q1:q10, ~ car::recode(.x,"'Instämmer inte alls'=0; 2=1; 3=2; 'Instämmer helt'=3; 'Vet ej'=NA; '<NA>'=NA", as.factor =FALSE))) %>%mutate(across(q11:q12, ~ car::recode(.x,"'Nej'=1; 'Ja'=0",as.factor =FALSE))) %>%mutate(q11q12 =case_when(q11 ==0| q12 ==0~0, q11 ==1& q12 ==1~1) ) %>%select(all_of(tts.items),Kön,Årskurs,Stadium) %>%mutate(Stadium =as.character(Stadium)) %>%# split() i nästa chunk funkar inte med en faktor-variabel om inte alla faktornivåer finns med. Det hade iofs gått bra att köra droplevel() ocksåna.omit() dif.tts.kön <- df.dif.tts$Köndif.tts.årskurs <- df.dif.tts$Årskursdif.tts.stadium <- df.dif.tts$Stadiumdf.dif.tts$Kön <-NULLdf.dif.tts$Årskurs <-NULL
Code
library(furrr)plan(multisession, workers =8)itemfit.time <- df.dif.tts %>%split(.$Stadium) %>%# split() funkar inte med en faktor-variabel om inte alla faktornivåer finns med, behöver kodas om till chrfuture_map(~RIitemfitPCM(subset(., select =-Stadium), table =FALSE), .options =furrr_options(seed =TRUE))stadier <-c("Lågstadiet","Mellanstadiet","Högstadiet")itemfit.all <-data.frame(matrix(ncol =4, nrow =0))colnames(itemfit.all) <-c("Item", "Stadium", 'InfitMSQ','OutfitMSQ')for (i in stadier) { itemfit.add <- itemfit.time[[i]] %>%rownames_to_column("Item") %>%add_column(Stadium = i) itemfit.all <-rbind(itemfit.all, itemfit.add)}
Targeting är mycket skev, det skiljer 1.8 logits mellan items och respondenter. Detta framgår också av reliabilitetskurvan, där endast ca 30% av respondenterna befinner sig i området med acceptabel reliabilitet.
5.4 Item-parametrar
Code
RIitemparams(df.index)
Threshold 1
Threshold 2
Threshold 3
Item location
q2
-0.80
-0.13
1.29
0.12
q3
-0.47
0.83
3.04
1.13
q5
-1.16
-0.06
1.40
0.06
q7
-0.71
-0.12
1.10
0.09
q8
-0.92
0.24
2.22
0.51
q9
-0.21
0.55
1.62
0.66
q10
-0.51
NA
NA
-0.51
5.5 Transformeringstabell
Förutsätter att item 10 har dikotomiserats genom att slå samman de två lägsta och de två högsta svarsalternativen. Det ger oss 6 frågor med 3 trösklar vardera och en fråga med en tröskel, alltså 6*3+1 = 19 som max på ordinal summapoäng.
Code
RIscoreSE(df.index)
Ordinal sum score
Logit score
Logit std.error
0
-3.44
NA
1
-2.62
1.02
2
-1.88
0.74
3
-1.42
0.63
4
-1.07
0.56
5
-0.77
0.52
6
-0.51
0.50
7
-0.27
0.48
8
-0.04
0.48
9
0.18
0.48
10
0.41
0.48
11
0.65
0.49
12
0.89
0.51
13
1.16
0.53
14
1.46
0.57
15
1.81
0.62
16
2.23
0.69
17
2.79
0.81
18
3.65
1.09
19
4.59
NA
6 DIF för trygghet/trivsel
Eftersom dessa enstaka frågor ofta särredovisas är det viktigt att undersöka jämförbarhet mellan kön och ålder.
df.viz %>%drop_na(q13,Kön) %>%filter(!q13 =="Jag känner mig trygg överallt på skolan") %>%ggplot(aes(x = q13, fill = Kön)) +geom_bar(position ="dodge") +# scale_y_continuous(limits = c(0,100), breaks = c(0,20,40,60,80,100)) +scale_x_discrete('', guide =guide_axis(n.dodge =2),labels =~str_wrap(.x, 8)) +scale_color_gender() +scale_fill_gender() +theme_minimal() +theme_rise() +labs(title ="Var känner du dig minst trygg på skolan?",subtitle ="Samtliga årtal",y ="Antal") +facet_wrap(~Stadium,ncol =1)
Code
df.viz %>%drop_na(q13,Kön) %>%filter(!q13 =="Jag känner mig trygg överallt på skolan") %>%ggplot(aes(x = q13, fill = Kön)) +geom_bar(position ="dodge") +# scale_y_continuous(limits = c(0,100), breaks = c(0,20,40,60,80,100)) +scale_x_discrete('', guide =guide_axis(n.dodge =3),labels =~str_wrap(.x, 8)) +scale_color_gender() +scale_fill_gender() +theme_minimal() +theme_rise() +labs(title ="Var känner du dig minst trygg på skolan?",subtitle ="Samtliga årtal",y ="Antal") +facet_wrap(~Årskurs) +theme(panel.border =element_rect(colour ="darkgrey", fill =NA))
Code
df.viz %>%select(q13,År,Stadium,Kön,Årskurs) %>%group_by(År,Stadium,Kön) %>%count(q13, .drop = F) %>%mutate(Andel = n *100/sum(n)) %>%ungroup() %>%filter(q13 =="Jag känner mig trygg överallt på skolan") %>%ggplot(aes(x = År, y = Andel, color = Kön, group = Kön)) +geom_point(size =2) +geom_line(linewidth =0.9) +scale_y_continuous(limits =c(0,100), breaks =c(0,20,40,60,80,100)) +scale_x_continuous('År', guide =guide_axis(n.dodge =2),labels =~str_wrap(.x, 8)) +scale_color_gender() +scale_fill_gender() +theme_minimal() +theme_rise() +labs(title ="Jag känner mig trygg överallt på skolan",y ="Andel") +facet_wrap(~Stadium)
7.4 Jag känner mig trygg i skolan
Även Skolinspektionen använder denna fråga och båda har fyra svarskategorier. Dock är det inte exakt samma svarskategorier. SI använder Stämmer helt och hållet, Stämmer ganska bra, Stämmer ganska dåligt, Stämmer inte alls, medan TTS har Instämmer helt, 3, 2, Instämmer inte alls. Därmed är det inte säkert att de är helt jämförbara.
---title: "Trygghet, Trivsel och Studiero"subtitle: "Sigtuna kommuns skolenkät"title-block-banner: "#009ca6"title-block-banner-color: "#FFFFFF"author: name: Magnus Johansson affiliation: RISE Research Institutes of Sweden affiliation-url: https://ri.se/shic orcid: 0000-0003-1669-592Xdate: last-modifiedformat: html: toc: true toc-depth: 3 toc-title: "Innehållsförteckning" embed-resources: true standalone: true page-layout: full logo: rise_logo_quarto.png mainfont: 'Lato' monofont: 'Roboto Mono' code-overflow: wrap code-tools: true code-fold: true number-sections: true fig-dpi: 150 layout-align: left linestretch: 1.6 theme: materiaexecute: echo: true warning: false message: false cache: trueeditor_options: markdown: wrap: 72 chunk_output_type: console#bibliography: grateful-refs.bib---```{r}#| label: setup#| include: falselibrary(arrow)library(ggrepel)library(car)library(grateful) # devtools::install_github("Pakillo/grateful")library(kableExtra)library(readxl)library(tidyverse)library(eRm)library(mirt)library(psych)library(ggplot2)library(psychotree)library(matrixStats)library(reshape)library(knitr)library(cowplot)library(formattable) library(RISEkbmRasch) # devtools::install_github("pgmj/RISEkbmRasch")library(glue)library(foreach)library(foreign)### some commands exist in multiple packages, here we define preferred ones that are frequently usedselect <- dplyr::selectcount <- dplyr::countrecode <- car::recoderename <- dplyr::renameRISEpalette1 <-colorRampPalette(colors =c("#009ca6", "#e83c63", "#ffe500"))(6)#scales::show_col(RISEpalette1)RISEpalette2 <-colorRampPalette(colors =c("#009ca6", "#e83c63", "#ffe500"))(8)#scales::show_col(RISEpalette2)gender_colors <-c("Pojke"="#F5A127", "Flicka"="#009CA6")scale_color_gender <-partial(scale_color_manual, values = gender_colors)scale_fill_gender <-partial(scale_fill_manual, values = gender_colors)```## Importera data```{r}df.all <-read.spss("~/RISE/SHIC - Data i Dialog - Data i Dialog/data/Sigtuna/TTS/Databas Sigtuna TTS.sav", to.data.frame =TRUE)df <- df.allspssLabels <- df %>%attr('variable.labels') %>%as.data.frame()names(df) <- spssLabels$.itemlabels <-data.frame(itemnr =paste0("q",c(1:34)),item =names(df[8:41]) ) %>%mutate(item =str_replace(item, "kännt", "känt"))write.csv(itemlabels, "TTSitemlabels.csv")names(df)[8:41] <-paste0("q",c(1:34))df <- df %>%mutate(Årskurs =str_replace(Årskurs, "Elever ", "")) %>%mutate( Årskurs =str_trim(Årskurs, side ="right"),Klass =str_trim(Klass, side ="right"),Skola =str_trim(`Skolans namn`, side ="right"), .after ="Kommun" ) %>%select(!`Skolans namn`) %>%mutate(Stadium =case_when( Årskurs %in%c("Åk 1", "Åk 2", "Åk 3") ~"Lågstadiet", Årskurs %in%c("Åk 4", "Åk 5", "Åk 6") ~"Mellanstadiet", Årskurs %in%c("Åk 7", "Åk 8", "Åk 9") ~"Högstadiet", Årskurs =="Förskoleklass"~"Förskoleklass",TRUE~NA ), .before ="Årskurs") %>%mutate( Årskurs =factor(Årskurs),Skola =factor(Skola),Klass =factor(Klass),Stadium =factor(Stadium) ) %>%mutate(Kön = car::recode(Kön, "'[Ej svar]'=NA"))årtal <-c(2017:2022)årskurser <- df %>%distinct(Årskurs) %>%pull(Årskurs)df.items <- df %>%select(starts_with("q"))```## Deskriptiva data::: panel-tabset### Totalt antal svar/stadium```{r}df %>%group_by(År,Stadium) %>%reframe(Antal =n()) %>%ggplot(aes(x = År, y = Antal, color = Stadium)) +geom_line(linewidth =1) +geom_point(size =3) +#scale_color_viridis_d() +scale_x_continuous(guide =guide_axis(n.dodge =1), breaks = årtal) +scale_y_continuous(limits =c(0,NA)) +labs(title ="Antal respondenter per år",subtitle ="Fördelat på stadium") +theme_minimal() +theme_rise() +theme(text =element_text(family ="Lato"))```### Totalt antal svar/årskurs```{r}df %>%group_by(År,Årskurs) %>%reframe(Antal =n()) %>%ggplot(aes(x = År, y = Antal, color = Årskurs)) +geom_line(linewidth =1) +geom_point(size =3) +#scale_color_viridis_d() +scale_x_continuous(guide =guide_axis(n.dodge =1), breaks = årtal) +scale_y_continuous(limits =c(0,NA)) +labs(title ="Antal respondenter per år",subtitle ="Fördelat på årskurs") +theme_minimal() +theme_rise() +theme(text =element_text(family ="Lato"))```### Stadium/kön```{r}df %>%drop_na(Kön) %>%group_by(År,Stadium,Kön) %>%reframe(Antal =n()) %>%ggplot(aes(x = År, y = Antal, color = Stadium)) +geom_line(linewidth =1) +geom_point(size =3) +#scale_color_viridis_d() +scale_x_continuous(guide =guide_axis(n.dodge =1), breaks = årtal) +scale_y_continuous(limits =c(0,NA)) +labs(title ="Antal respondenter per år",subtitle ="Fördelat på stadium och kön") +theme_minimal() +theme_rise() +theme(text =element_text(family ="Lato")) +facet_wrap(~Kön)```:::## Frågor i enkäten```{r}itemlabels %>%slice(c(1:10,14:15,27:30,32:34)) %>%kbl_rise()```Ovanstående frågor har fyra svarskategorier, där bara ändpunkterna har etiketter (Instämmer helt - Instämmer inte alls), samt alternativet "Vet ej".Fråga 11-12 kan besvaras med Ja/Nej.- q11: Har du varit utsatt för kränkning på din skola i år?- q12: Har du varit utsatt för upprepade kränkningar på din skola i år?```{r}itemlabels %>%slice(c(27:30,32:34)) %>%kbl_rise()```Fråga 27-30 handlar om fritidshemmet, medan 31-34 handlar om modersmålsundervisning.Fråga 13 är "Var känner du dig minst trygg på skolan?", med följande åtta möjliga svarsalternativ:```{r}df %>%distinct(q13) %>%filter(!q13 =="NA") %>%rename(`Var känner du dig minst trygg på skolan?`= q13) %>%kbl_rise()```Frågorna 16-22 handlar om de sju diskrimineringsgrunderna, och fråga 23 blir svårtolkad. Ska man svara "Ja" på den om man blivit illa behandlad på grund av något annat än de sju diskrimineringsgrunderna, eller om man inte alls blivit illa behandlad? Vad betyder "Nej" på den frågan?Fråga 24 och 25 handlar om utsatthet för sexuella trakasserier någon gång under året (oavsett plats) samt om det hänt upprepade gånger på skolan (Ja/nej/vet ej).```{r}itemlabels %>%slice(c(16:23)) %>%kbl_rise()```## Explorativ analysVi lägger in fråga 1-12 i en analys för att se om de kan användas tillsammans för att estimera indexvärden. Initialt tittar vi enbart på data från högstadiet.```{r}#| layout-ncol: 2df %>%filter(Stadium =="Högstadiet") %>%pull(Kön) %>%RIdemographics(.,"Kön")df %>%filter(Stadium =="Högstadiet") %>%pull(Årskurs) %>%RIdemographics(.,"Årskurs")df %>%filter(Stadium =="Högstadiet") %>%pull(År) %>%RIdemographics(.,"År")```Först tittar vi på rådata.```{r}library(skimr)df %>%filter(Stadium =="Högstadiet") %>%select(q1:q12) %>%skim()```### Missing data```{r}df %>%filter(Stadium =="Högstadiet") %>%select(q1:q12) %>%RImissing()```Fyra items har exakt samma struktur. Det antyder dels att data är "tvättade" redan, och att det rör sig om items som tillkommit/tagits bort vid någon datainsamling.Låt oss titta på andelen missing data (NA) per år.```{r}#| fig-height: 8df %>%select(q1:q12,År,Kön) %>%#filter(År >= 2013) %>% drop_na(Kön) %>%pivot_longer(q1:q12, names_to ="Item", values_to ="Svarskategori") %>%group_by(År,Kön,Item) %>%count(Svarskategori) %>%mutate(Andel =100* n /sum(n)) %>%#filter(Svarskategori %in% c("Vet inte",NA)) %>% ggplot(aes(x =factor(År), y = Andel, group = Kön, color = Kön, fill = Kön)) +geom_point(size =1.2, alpha =0.85) +geom_line(linewidth =0.4, alpha =0.85) +#scale_y_continuous(limits = c(0,100), breaks = c(0,20,40,60,80,100)) +scale_color_manual(values = RISEpalette1) +scale_x_discrete(guide =guide_axis(n.dodge =2)) +labs(title ="Fördelning av svar items q1-q12",subtitle ="Samtliga årskurser") +ylab("Andel respondenter i procent") +xlab("Årtal") +theme_rise() +theme_minimal(base_size =9) +facet_grid(Item~Svarskategori,switch ="y") +theme(legend.position ="top")```Vi kodar om svarskategorierna till siffror inför analysen, och tar bort alla respondenter med missing data. Högre värden = bättre, så gällande fråga 11-12 kodas Ja = 0 och Nej = 1.```{r}df.index <- df %>%filter(Stadium =="Högstadiet") %>%select(q1:q12) %>%mutate(across(q1:q10, ~ car::recode(.x,"'Instämmer inte alls'=0; 2=1; 3=2; 'Instämmer helt'=3; 'Vet ej'=NA; '<NA>'=NA", as.factor =FALSE))) %>%mutate(across(q11:q12, ~ car::recode(.x,"'Nej'=1; 'Ja'=0",as.factor =FALSE))) %>%na.omit()```### Deskriptiva data```{r}#| column: margin#| echo: falseRIlistItemsMargin(df.index, fontsize =12)```::: panel-tabset#### Tileplot```{r}RItileplot(df.index) +theme_minimal() +theme_rise()```#### Stacked bars```{r}RIbarstack(df.index) +theme_minimal() +theme_rise()```#### Barplots```{r}#| layout-ncol: 2RIbarplot(df.index)```#### Heatmap```{r}RIheatmap(df.index)```:::### Rasch-analys 1 samtliga items```{r}#| column: margin#| echo: falseRIlistItemsMargin(df.index, fontsize =12)```::: panel-tabset#### Item fit```{r}RIitemfitPCM2(df.index, 250, 32, 8)```#### 1st contrast loadings```{r}RIloadLoc(df.index)```#### PCA av residualer```{r}RIpcmPCA(df.index)```#### Residualkorrelationer```{r}RIresidcorr(df.index, 0.2)```#### Targeting```{r}#| fig-height: 6RItargeting(df.index)```#### Item-hierarki```{r}#| fig-height: 6RIitemHierarchy(df.index)```:::Item fit ser bra ut. PCA eigenvalue och residualkorrelationer visar på att flera frågor är väldigt lika varandra. Tydligast är q11 och 12, vilket är förväntat eftersom de handlar om samma sak med olika svårighetsgrad. HI övrigt är det främst stora residualkorrelationer mellan:- q1 och 2 (trivs i skolan/klassen)- q3 och 4 (koncentrera mig/jobba på lektionerna)- q1 och 6 (trivs och trygg)- q6 och 8 (bra bemött och trygg)Figuren med faktorladdningar på första kontrastfaktorn visar en möjlig delning i två kluster:- 1, 2, 6, 8, 11 och 12 (trivsel, trygghet, frånvaro av kränkningar)- 3, 4, 5, 7, 9, 10 (studiero, vuxnas bemötande)Vi provar att köra två separata analyser.### Rasch-analys 1 trivsel/trygghet```{r}df.ttf <- df %>%filter(Stadium =="Högstadiet") %>%mutate(across(q1:q10, ~ car::recode(.x,"'Instämmer inte alls'=0; 2=1; 3=2; 'Instämmer helt'=3; 'Vet ej'=NA; '<NA>'=NA", as.factor =FALSE))) %>%mutate(across(q11:q12, ~ car::recode(.x,"'Nej'=0; 'Ja'=1",as.factor =FALSE))) %>%#mutate(q11_12 = q11 + q12) %>% select(q1,q2,q6,q8,q11,q12) %>%na.omit() # itemlabels <- rbind(itemlabels,c("q11_12","Har du varit utsatt för (upprepad) kränkning på din skola i år?"))``````{r}RItileplot(df.ttf)``````{r}#| column: margin#| echo: falseRIlistItemsMargin(df.ttf, fontsize =13)```::: panel-tabset#### Item fit```{r}#| cache: trueRIitemfitPCM2(df.ttf, samplesize =250, nsamples =32, cpu =8)```#### PCA```{r}#| tbl-cap: "PCA of Rasch model residuals"RIpcmPCA(na.omit(df.ttf))```#### Residual correlations```{r}RIresidcorr(df.ttf, cutoff =0.2)```#### 1st contrast loadings```{r}RIloadLoc(df.ttf)```#### Analysis of response categories```{r}#| layout-ncol: 2RIitemCats(df.ttf, items ="all", xlims =c(-5,5))```#### Targeting```{r}#| fig-height: 5# increase fig-height above as needed, if you have many itemsRItargeting(df.ttf)```#### Item hierarchy```{r}#| fig-height: 5RIitemHierarchy(df.ttf)```#### Person fit```{r}RIpfit(df.ttf)```#### Reliability```{r}RItif(df.ttf)```:::I denna uppsättning items är det tydligt att q11 och q12 tillhör en separat dimension.Vi tar bort dessa items och ser hur de andra fungerar utan dem.### Rasch-analys 2 trivsel & trygghet```{r}df.ttf$q11 <-NULLdf.ttf$q12 <-NULL``````{r}#| column: margin#| echo: falseRIlistItemsMargin(df.ttf, fontsize =13)```::: panel-tabset#### Item fit```{r}#| cache: trueRIitemfitPCM2(df.ttf, samplesize =250, nsamples =32, cpu =8)```#### PCA```{r}#| tbl-cap: "PCA of Rasch model residuals"RIpcmPCA(na.omit(df.ttf))```#### Residual correlations```{r}RIresidcorr(df.ttf, cutoff =0.2)```#### 1st contrast loadings```{r}RIloadLoc(df.ttf)```#### Analysis of response categories```{r}#| layout-ncol: 2RIitemCats(df.ttf, items ="all", xlims =c(-5,5))```#### Targeting```{r}#| fig-height: 5# increase fig-height above as needed, if you have many itemsRItargeting(df.ttf)```#### Item hierarchy```{r}#| fig-height: 5RIitemHierarchy(df.ttf)```#### Person fit```{r}RIpfit(df.ttf)```#### Reliability```{r}RItif(df.ttf)```:::Dessa items fungerar även om flera har låg item fit, men har låg reliabilitet tillsammans. Vi kan eventuellt använda sammansättningen items för att testa invarians/DIF för frågorna (kommer längre ner i denna analys).### Rasch-analys 1 studiero```{r}df.studiero <- df.index %>%select(!any_of(c("q1","q2","q6","q8","q11","q12")))``````{r}RItileplot(df.studiero)``````{r}#| column: margin#| echo: falseRIlistItemsMargin(df.studiero, fontsize =13)```::: panel-tabset#### Item fit```{r}#| cache: trueRIitemfitPCM2(df.studiero, samplesize =250, nsamples =32, cpu =8)```#### PCA```{r}#| tbl-cap: "PCA of Rasch model residuals"RIpcmPCA(na.omit(df.studiero))```#### Residual correlations```{r}RIresidcorr(df.studiero, cutoff =0.2)```#### 1st contrast loadings```{r}RIloadLoc(df.studiero)```#### Analysis of response categories```{r}#| layout-ncol: 2RIitemCats(df.studiero, items ="all", xlims =c(-5,5))```#### Targeting```{r}#| fig-height: 5# increase fig-height above as needed, if you have many itemsRItargeting(df.studiero)```#### Item hierarchy```{r}#| fig-height: 5RIitemHierarchy(df.studiero)```#### Person fit```{r}RIpfit(df.studiero)```#### Reliability```{r}RItif(df.studiero)```:::Item q3 och 4 har en stark residualkorrelation och en av dem behöver tas bort. Vi tar bort q4 eftersom den har något lägre item fit och targeting jämfört med q3.### Rasch-analys 2 studiero```{r}df.studiero$q4 <-NULL``````{r}#| column: margin#| echo: falseRIlistItemsMargin(df.studiero, fontsize =13)```::: panel-tabset#### Item fit```{r}#| cache: trueRIitemfitPCM2(df.studiero, samplesize =250, nsamples =32, cpu =8)```#### PCA```{r}#| tbl-cap: "PCA of Rasch model residuals"RIpcmPCA(na.omit(df.studiero))```#### Residual correlations```{r}RIresidcorr(df.studiero, cutoff =0.2)```#### 1st contrast loadings```{r}RIloadLoc(df.studiero)```#### Targeting```{r}#| fig-height: 5# increase fig-height above as needed, if you have many itemsRItargeting(df.studiero, xlim =c(-4,5))```#### Item hierarchy```{r}#| fig-height: 5RIitemHierarchy(df.studiero)```#### Person fit```{r}RIpfit(df.studiero)```#### Reliability```{r}RItif(df.studiero)```:::Det är små skillnader mellan T1 och T2 för q10, men de är inte oordnade. I övrigt ser allt acceptabelt ut, dock med en tydlig takeffekt och låg reliabilitet.Vi återgår till att titta på samtliga items tillsammans och se om det går att ta fram ett fungerande index.### Rasch-analys 2 samtliga itemsUtifrån vår tidigare analys fanns en del residualkorrelationer att hantera. Vi börjar med att ta bort:- q4 (q3 har bättre targeting)Samt att vi slår samman q11 och q12, där svaret "Ja" på någon av frågorna blir "Ja" (0) i den nya frågan, och den som svarat "Nej" på båda frågorna blir "Nej" (1). Vi kodar fortfarande konsekvent så att högre värden = bättre/mera önskvärt resultat.Det är inte optimalt att ställa två ja/nej-frågor med i princip samma innehåll men olika frekvenspåståenden. Om det i stället hade funnits en enda fråga om utsatthet för kränkning med flera frekvenspåståenden hade det fungerat betydligt bättre. Som det är nu uppstår t.ex. situationen där den som blivit utsatt för flera kränkningar kan svara "Nej" på om den blivit utsatt för en kränkning.```{r}df.index <- df %>%filter(Stadium =="Högstadiet") %>%select(q1:q12) %>%mutate(across(q1:q10, ~ car::recode(.x,"'Instämmer inte alls'=0; 2=1; 3=2; 'Instämmer helt'=3; 'Vet ej'=NA; '<NA>'=NA", as.factor =FALSE))) %>%mutate(across(q11:q12, ~ car::recode(.x,"'Nej'=1; 'Ja'=0",as.factor =FALSE))) %>%na.omit() %>%mutate(q11q12 =case_when(q11 ==0| q12 ==0~0, q11 ==1& q12 ==1~1) ) %>%select(!any_of(c("q4","q11","q12")))RItileplot(df.index)itemlabels <-rbind(itemlabels,c("q11q12","Har du varit utsatt för en eller flera kränkningar på din skola i år?"))``````{r}#| column: margin#| echo: falseRIlistItemsMargin(df.index, fontsize =12)```::: panel-tabset#### Item fit```{r}RIitemfitPCM2(df.index, 250, 32, 8)```#### 1st contrast loadings```{r}RIloadLoc(df.index)```#### PCA av residualer```{r}RIpcmPCA(df.index)```#### Residualkorrelationer```{r}RIresidcorr(df.index, 0.2)```#### Targeting```{r}#| fig-height: 6RItargeting(df.index)```#### Item-hierarki```{r}#| fig-height: 6RIitemHierarchy(df.index)```:::Som väntat ligger de generella frågorna q1 och q6 lågt i item fit, och korrelerar med andra frågor.Vi har problematiska residualkorrelationer:- q1 med q2 och q6 (trivs i skolan; trivs i klassen; känner mig trygg i skolan )- q6 med q8 (och q1), där 8 = blir bra bemött av eleverVi tar bort q1 först.```{r}df.index %>%select(!q1) %>%RIresidcorr(0.2)```6 korrelerar med både 2 och 8, vi tar bort den med.```{r}df.index <- df.index %>%select(!q1) %>%select(!q6)```### Rasch-analys 3 samtliga items```{r}#| column: margin#| echo: falseRIlistItemsMargin(df.index, fontsize =12)```::: panel-tabset#### Item fit```{r}RIitemfitPCM2(df.index, 250, 32, 8)```#### 1st contrast loadings```{r}RIloadLoc(df.index)```#### PCA av residualer```{r}RIpcmPCA(df.index)```#### Residualkorrelationer```{r}RIresidcorr(df.index, 0.2)```#### Targeting```{r}#| fig-height: 6RItargeting(df.index)```#### Item-hierarki```{r}#| fig-height: 6RIitemHierarchy(df.index)```#### Reliabilitet```{r}RItif(df.index)```#### Svarskategorier```{r}RIitemCats(df.index)```#### Person fit```{r}RIpfit(df.index)```:::Två korrelationer strax över gränsvärdet, vilket inte är problematiskt.```{r}RIlistitems(df.index)```### DIF TTS-indexVi behöver undersöka huruvida frågorna fungerar olika för subgrupper, i detta fall kön och årskurs/stadium.```{r}studiero.items <-names(df.studiero)ttf.items <-names(df.ttf)tts.items <-names(df.index)```Vi börjar med enbart högstadiet. "Annat/Vill ej svara" är en för liten grupp, så den kodas som missing.Funktionen som gör DIF-analysen fungerar inte korrekt när item q11 är med, eftersom det bara har två svarskategorier. Vi gör därför LRT-analyser som inkluderar q11, och DIF-analyser utan q11. LRT står för Likelihood Ratio Test. Eftersom vi har väldigt stora sampel är det hög sannolikhet att få statistisk signifikans i dessa test, även om skillnaderna är såpass små att de inte är relevanta. Därför behöver vi även undersöka storleken av effekterna på item-nivå.```{r}df.dif.tts <- df %>%filter(Stadium =="Högstadiet") %>%mutate(Kön = car::recode(Kön,"'Annat/Vill ej svara'=NA")) %>%#drop_na(Stadium, Kön) %>% mutate(across(q1:q10, ~ car::recode(.x,"'Instämmer inte alls'=0; 2=1; 3=2; 'Instämmer helt'=3; 'Vet ej'=NA; '<NA>'=NA", as.factor =FALSE))) %>%mutate(across(q11:q12, ~ car::recode(.x,"'Nej'=1; 'Ja'=0",as.factor =FALSE))) %>%mutate(q11q12 =case_when(q11 ==0| q12 ==0~0, q11 ==1& q12 ==1~1) ) %>%select(all_of(tts.items),Kön,Årskurs,Stadium) %>%na.omit() dif.tts.kön <- df.dif.tts$Köndif.tts.årskurs <- df.dif.tts$Årskursdif.tts.stadium <-factor(df.dif.tts$Stadium,levels =c("Lågstadiet","Mellanstadiet","Högstadiet"))df.dif.tts$Kön <-NULLdf.dif.tts$Årskurs <-NULLdf.dif.tts$Stadium <-NULL``````{r}#| column: margin#| echo: falseRIlistItemsMargin(df.dif.tts, fontsize =12)```#### Kön::: panel-tabset##### LRT ```{r}RIdifTableLR(df.dif.tts, dif.tts.kön)```##### LRT figure```{r}RIdifFigureLR(df.dif.tts, dif.tts.kön)```##### LRT thresholds```{r}RIdifThreshFigLR(df.dif.tts, dif.tts.kön)```##### utan q11q12 (annan metod)```{r}df.dif.tts %>%select(!q11q12) %>%RIdifTable(., dif.tts.kön)```##### Thresholds utan q11q12```{r}df.dif.tts %>%select(!q11q12) %>%RIdifFigThresh(., dif.tts.kön)```:::Väldigt olika utfall mellan de två DIF-metoderna. Men eftersom ingen av dem indikerar DIF för q11q12 väljer vi att gå på analys-metoden som plockar bort q11q12.::: panel-tabset#### Årskurs```{r}#| column: margin#| echo: falseRIlistItemsMargin(df.dif.tts, fontsize =12)```#### LRT```{r}RIdifTableLR(df.dif.tts, dif.tts.årskurs)```##### utan q11q12 (annan metod)```{r}df.dif.tts %>%select(!q11q12) %>%RIdifTable(., dif.tts.årskurs)```:::#### Interaktion kön/årskurs```{r}#| column: margin#| echo: falseRIlistItemsMargin(df.dif.tts, fontsize =12)``````{r}#| fig-height: 4df.dif.tts %>%select(!q11q12) %>%RIdifTable2(., dif.tts.kön, dif.tts.årskurs)```Item 8 får något högre maxvärde här, men fortfarande under 0.5.#### StadiumVi tar inte med förskoleklass, som har lite data.```{r}df.dif.tts <- df %>%filter(!Stadium =="Förskoleklass") %>%mutate(Kön = car::recode(Kön,"'Annat/Vill ej svara'=NA")) %>%drop_na(Stadium, Kön) %>%mutate(across(q1:q10, ~ car::recode(.x,"'Instämmer inte alls'=0; 2=1; 3=2; 'Instämmer helt'=3; 'Vet ej'=NA; '<NA>'=NA", as.factor =FALSE))) %>%mutate(across(q11:q12, ~ car::recode(.x,"'Nej'=1; 'Ja'=0",as.factor =FALSE))) %>%mutate(q11q12 =case_when(q11 ==0| q12 ==0~0, q11 ==1& q12 ==1~1) ) %>%select(all_of(tts.items),Kön,Årskurs,Stadium,År) %>%na.omit() dif.tts.kön <- df.dif.tts$Köndif.tts.årskurs <- df.dif.tts$Årskursdif.tts.stadium <-factor(df.dif.tts$Stadium,levels =c("Lågstadiet","Mellanstadiet","Högstadiet"))dif.tts.år <- df.dif.tts$Årdf.dif.tts$Kön <-NULLdf.dif.tts$Årskurs <-NULLdf.dif.tts$Stadium <-NULLdf.dif.tts$År <-NULL``````{r}#| column: margin#| echo: falseRIlistItemsMargin(df.dif.tts, fontsize =12)```::: panel-tabset##### LRT```{r}#| fig-height: 4RIdifTableLR(df.dif.tts, dif.tts.stadium)```##### PsTree```{r}df.dif.tts %>%select(!q11q12) %>%RIdifTable(., dif.tts.stadium) ```:::Här finns tecken på att q11q12 fungerar olika mellan stadier.#### DIF kön (samtliga åk 1-9)```{r}#| fig-height: 3df.dif.tts %>%select(!q11q12) %>%RIdifTable(., dif.tts.kön) ```##### Årtal```{r}#| fig-height: 5df.dif.tts %>%select(!q11q12) %>%RIdifTable(., dif.tts.år) ```:::##### DIF item fit```{r}df.dif.tts <- df %>%filter(!Stadium =="Förskoleklass") %>%mutate(Kön = car::recode(Kön,"'Annat/Vill ej svara'=NA")) %>%drop_na(Stadium,Kön) %>%mutate(across(q1:q10, ~ car::recode(.x,"'Instämmer inte alls'=0; 2=1; 3=2; 'Instämmer helt'=3; 'Vet ej'=NA; '<NA>'=NA", as.factor =FALSE))) %>%mutate(across(q11:q12, ~ car::recode(.x,"'Nej'=1; 'Ja'=0",as.factor =FALSE))) %>%mutate(q11q12 =case_when(q11 ==0| q12 ==0~0, q11 ==1& q12 ==1~1) ) %>%select(all_of(tts.items),Kön,Årskurs,Stadium) %>%mutate(Stadium =as.character(Stadium)) %>%# split() i nästa chunk funkar inte med en faktor-variabel om inte alla faktornivåer finns med. Det hade iofs gått bra att köra droplevel() ocksåna.omit() dif.tts.kön <- df.dif.tts$Köndif.tts.årskurs <- df.dif.tts$Årskursdif.tts.stadium <- df.dif.tts$Stadiumdf.dif.tts$Kön <-NULLdf.dif.tts$Årskurs <-NULL``````{r}library(furrr)plan(multisession, workers =8)itemfit.time <- df.dif.tts %>%split(.$Stadium) %>%# split() funkar inte med en faktor-variabel om inte alla faktornivåer finns med, behöver kodas om till chrfuture_map(~RIitemfitPCM(subset(., select =-Stadium), table =FALSE), .options =furrr_options(seed =TRUE))stadier <-c("Lågstadiet","Mellanstadiet","Högstadiet")itemfit.all <-data.frame(matrix(ncol =4, nrow =0))colnames(itemfit.all) <-c("Item", "Stadium", 'InfitMSQ','OutfitMSQ')for (i in stadier) { itemfit.add <- itemfit.time[[i]] %>%rownames_to_column("Item") %>%add_column(Stadium = i) itemfit.all <-rbind(itemfit.all, itemfit.add)}``````{r}itemfit.all %>%group_by(Item) %>%summarise(mean_Out =mean(OutfitMSQ),sd_Out =sd(OutfitMSQ),max_Out =max(OutfitMSQ),min_Out =min(OutfitMSQ),mean_In =mean(InfitMSQ),sd_In =sd(InfitMSQ),max_In =max(InfitMSQ),min_In =min(InfitMSQ) ) %>%mutate(diffmax_OutfitMSQ = max_Out - min_Out,diffmax_InfitMSQ = max_In - min_In,item = Item ) %>%mutate(across(where(is.numeric), ~round(.x, 2))) %>%mutate(across(starts_with(c("max", "min")), ~cell_spec(.x, color =ifelse(.x <0.7, "red",ifelse(.x >1.3, "red", "black") )))) %>%kbl(booktabs = T, escape = F,col.names =c("Item","Mean","SD","Max","Min","Mean","SD","Max","Min","OutfitMSQ","InfitMSQ","Item")) %>%# bootstrap options are for HTML outputkable_styling(bootstrap_options =c("striped", "hover"),position ="left",full_width = F,font_size =15,fixed_thead = T ) %>%column_spec(c(1, 12), bold = T) %>%kable_classic(html_font ="Lato") %>%# latex_options are for PDF outputkable_styling(latex_options =c("striped", "scale_down")) %>%add_header_above(c(" "=1, "OutfitMSQ"=4, "InfitMSQ"=4, "Max differences"=2," "=1))```## Rasch-analys 4Först tas q11q12 bort. ```{r}df.index <- df.dif.tts %>%select(!q11q12) %>%select(!Stadium)```Vi lägger nu in alla responser från alla år och årskurser::: panel-tabset#### Item fit```{r}RIitemfitPCM2(df.index, 250, 32, 8)```#### 1st contrast loadings```{r}RIloadLoc(df.index)```#### PCA av residualer```{r}RIpcmPCA(df.index)```#### Residualkorrelationer```{r}RIresidcorr(df.index, 0.2)```#### Targeting```{r}#| fig-height: 6RItargeting(df.index)```#### Item-hierarki```{r}#| fig-height: 6RIitemHierarchy(df.index)```#### Svarskategorier```{r}RIitemCats(df.index)```:::Item q10 har oordnade svarskategorier, de två lägsta och de två högsta slås ihop.```{r}df.index$q10 <- car::recode(df.index$q10,"1=0;2=1;3=1")```### Targeting```{r}RItargeting(df.index)```### Reliabilitet```{r}RItif(df.index)```### Person fit```{r}RIpfit(df.index)```Targeting är mycket skev, det skiljer 1.8 logits mellan items och respondenter. Detta framgår också av reliabilitetskurvan, där endast ca 30% av respondenterna befinner sig i området med acceptabel reliabilitet.### Item-parametrar```{r}RIitemparams(df.index)```### TransformeringstabellFörutsätter att item 10 har dikotomiserats genom att slå samman de två lägsta och de två högsta svarsalternativen. Det ger oss 6 frågor med 3 trösklar vardera och en fråga med en tröskel, alltså 6*3+1 = 19 som max på ordinal summapoäng.```{r}RIscoreSE(df.index)```## DIF för trygghet/trivselEftersom dessa enstaka frågor ofta särredovisas är det viktigt att undersöka jämförbarhet mellan kön och ålder.```{r}df.dif.tts <- df %>%filter(!Stadium =="Förskoleklass") %>%mutate(Kön = car::recode(Kön,"'Annat/Vill ej svara'=NA")) %>%drop_na(Stadium, Kön) %>%mutate(across(q1:q10, ~ car::recode(.x,"'Instämmer inte alls'=0; 2=1; 3=2; 'Instämmer helt'=3; 'Vet ej'=NA; '<NA>'=NA", as.factor =FALSE))) %>%mutate(across(q11:q12, ~ car::recode(.x,"'Nej'=1; 'Ja'=0",as.factor =FALSE))) %>%mutate(q11q12 =case_when(q11 ==0| q12 ==0~0, q11 ==1& q12 ==1~1) ) %>%select(q1:q10,Kön,Årskurs,Stadium,År) %>%select(!q4) %>%na.omit() dif.tts.kön <- df.dif.tts$Köndif.tts.årskurs <- df.dif.tts$Årskursdif.tts.stadium <-factor(df.dif.tts$Stadium,levels =c("Lågstadiet","Mellanstadiet","Högstadiet"))dif.tts.år <- df.dif.tts$Årdf.dif.tts$Kön <-NULLdf.dif.tts$Årskurs <-NULLdf.dif.tts$Stadium <-NULLdf.dif.tts$År <-NULL```Vi behöver även undersöka stabiliteten i item fit, åtminstone fördelat på stadium. För detta ändamål återinför vi items 1 och 6.::: panel-tabset### Kön```{r}RIdifTable(df.dif.tts, dif.tts.kön)```### Stadium```{r}RIdifTable(df.dif.tts, dif.tts.stadium)```### Årskurs```{r}RIdifTable(df.dif.tts, dif.tts.årskurs)```### År```{r}RIdifTable(df.dif.tts, dif.tts.år)```### Kön/stadium```{r}RIdifTable2(df.dif.tts, dif.tts.stadium, dif.tts.kön)```:::## Visualiseringar```{r}df <- df %>%mutate(diskriminerad =case_when(q16 =="Chosen"~"Kön", q17 =="Chosen"~"Etnisk bakgrund", q18 =="Chosen"~"Religion eller trosuppfattning", q19 =="Chosen"~"Funktionshinder", q20 =="Chosen"~"Sexuell läggning", q21 =="Chosen"~"Ålder", q22 =="Chosen"~"Könsidentitet/ könsuttryck", q23 =="Chosen"~"Annat",TRUE~"Ej diskriminerad" )) %>%mutate(diskriminerad =factor(diskriminerad))#df %>% count(diskriminerad)``````{r}df.viz <- df %>%filter(!Stadium =="Förskoleklass") %>%mutate(Kön = car::recode(Kön,"'Annat/Vill ej svara'=NA")) %>%drop_na(Stadium,Kön,Årskurs,År) %>%# mutate(across(q1:q10, ~ car::recode(.x,"'Instämmer inte alls'=0;# 2=1;# 3=2;# 'Instämmer helt'=3;# 'Vet ej'=NA;# '<NA>'=NA", # as.factor = FALSE))) %>% # mutate(across(q11:q12, ~ car::recode(.x,"'Nej'=1;# 'Ja'=0",# as.factor = FALSE))) %>% mutate(q11q12 =case_when(q11 =='Nej'& q12 =='Nej'~'Nej', q11 =='Ja'| q12 =='Ja'~'Ja',TRUE~NA) ) %>%select(q1:q34,q11q12,diskriminerad,Kön,Årskurs,Stadium,År,Skola) %>%mutate(Årskurs =droplevels(Årskurs),Stadium =droplevels(Stadium)) %>%mutate(Stadium =factor(Stadium, levels =c("Lågstadiet","Mellanstadiet","Högstadiet")))```### q11 och q12:::: column-page-left::: panel-tabset#### Antal```{r}df.viz %>%select(q11,q12,Årskurs,Kön) %>%na.omit() %>%pivot_longer(q11:q12,names_to ="item",values_to ="svarskategori") %>%ggplot(aes(x = svarskategori, fill = Kön)) +geom_bar(position ="dodge") +facet_grid(item~Årskurs) +scale_fill_gender() +theme_rise() +theme_minimal() +labs(title ="Utsatt för kränkningar - antal",y ="Antal",x ="")```#### Andel```{r}df.viz %>%select(q11,q12,Årskurs,Kön) %>%na.omit() %>%pivot_longer(q11:q12,names_to ="item",values_to ="svarskategori") %>%group_by(Årskurs,Kön,item) %>%count(svarskategori) %>%mutate(Andel = n *100/sum(n)) %>%ungroup() %>%ggplot(aes(x = svarskategori, y = Andel, fill = Kön)) +geom_col(position ="dodge") +facet_grid(item~Årskurs) +scale_fill_gender() +theme_rise() +theme_minimal() +labs(title ="Utsatt för kränkningar - andel i %",y ="Andel",x ="") +scale_y_continuous(limits =c(0,100))```#### Andel/årskurs "Ja" (linje)```{r}df.viz %>%select(q11,q12,Årskurs,Kön) %>%pivot_longer(c("q11","q12"),names_to ="item",values_to ="svarskategori") %>%group_by(Årskurs,Kön,item) %>%count(svarskategori) %>%mutate(Andel = n *100/sum(n)) %>%ungroup() %>%filter(svarskategori =="Ja") %>%ggplot(aes(x = Årskurs, y = Andel, color = Kön, group = Kön)) +geom_point(size =2.5) +geom_line(linewidth =1.1) +facet_wrap(~item) +scale_color_gender() +theme_rise() +theme_minimal() +labs(title ="Utsatt för kränkningar - andel i %",y ="Andel",x ="") +scale_y_continuous(limits =c(0,100))```#### Andel/årskurs "Nej" (linje)```{r}df.viz %>%select(q11,q12,Årskurs,Kön) %>%pivot_longer(c("q11","q12"),names_to ="item",values_to ="svarskategori") %>%group_by(Årskurs,Kön,item) %>%count(svarskategori) %>%mutate(Andel = n *100/sum(n)) %>%ungroup() %>%filter(svarskategori =="Nej") %>%ggplot(aes(x = Årskurs, y = Andel, color = Kön, group = Kön)) +geom_point(size =2.5) +geom_line(linewidth =1.1) +facet_wrap(~item) +scale_color_gender() +theme_rise() +theme_minimal() +labs(title ="Ej utsatt för kränkningar - andel i %",y ="Andel",x ="") +scale_y_continuous(limits =c(0,100))```#### Andel/årskurs "Ja" över tid```{r}#| fig-width: 10#| fig-height: 6df.viz %>%select(q11,q12,Årskurs,Kön,År) %>%pivot_longer(c("q11","q12"),names_to ="item",values_to ="svarskategori") %>%group_by(År,Årskurs,Kön,item) %>%count(svarskategori) %>%mutate(Andel = n *100/sum(n)) %>%ungroup() %>%filter(svarskategori =="Ja") %>%ggplot(aes(x = År, y = Andel, color = Kön, group = Kön)) +geom_point(size =2) +geom_line(linewidth =1) +facet_grid(item~Årskurs) +scale_color_gender() +theme_rise() +theme_minimal() +labs(title ="Utsatt för kränkningar - andel i %",y ="Andel",x ="") +scale_y_continuous(limits =c(0,100), minor_breaks =NULL, breaks =c(0,20,40,60,80,100)) +scale_x_continuous(guide =guide_axis(n.dodge =2)) +theme(panel.border =element_rect(color ="darkgrey", fill =NA))```:::::::### Diskriminering```{r}df %>%select(q16:q23) %>%mutate(across(everything(), ~as.numeric(.x))) %>%RItileplot()```q23 - "Har du känt dig illa/annorlunda behandlad på din skola i år på grund av: - Inget av ovanstående"q23 är tvetydig, och kodas först som "Annat" i nedanstående figur.:::: column-page-left::: panel-tabset#### Figur 1```{r}#| fig-width: 10#| fig-height: 6df.viz %>%filter(!diskriminerad =="Ej diskriminerad") %>%filter(Årskurs %in%c("Åk 7","Åk 8", "Åk 9")) %>%mutate(Årskurs =droplevels(Årskurs),diskriminerad =droplevels(diskriminerad)) %>%drop_na(diskriminerad) %>%group_by(År,Årskurs,Kön) %>%count(diskriminerad, .drop = F) %>%mutate(Andel =100*n/sum(n)) %>%mutate(diskriminerad =fct_reorder(diskriminerad, desc(n))) %>%ggplot(data = .,aes(x = År, y = Andel, fill = Kön)) +geom_bar(position =position_dodge(),stat ='identity') +scale_y_continuous(limits =c(0,100), breaks =c(0,20,40,60,80,100)) +scale_x_continuous('År', guide =guide_axis(n.dodge =2)) +scale_color_gender() +scale_fill_gender() +theme_minimal() +theme_rise() +facet_grid(Årskurs~diskriminerad,labeller =labeller(diskriminerad =label_wrap_gen(16))) ```#### Figur 2Vi tar bort Annat och justerar y axeln så vi bättre kan se utveckling över tid.```{r}#| fig-width: 10#| fig-height: 6df.viz %>%filter(!diskriminerad %in%c("Ej diskriminerad","Annat")) %>%filter(Årskurs %in%c("Åk 7","Åk 8", "Åk 9")) %>%mutate(Årskurs =droplevels(Årskurs),diskriminerad =droplevels(diskriminerad)) %>%drop_na(diskriminerad) %>%group_by(År,Årskurs,Kön) %>%count(diskriminerad, .drop = F) %>%mutate(Andel =100*n/sum(n)) %>%mutate(diskriminerad =fct_reorder(diskriminerad, desc(n))) %>%ggplot(data = .,aes(x = År, y = Andel, fill = Kön)) +geom_bar(position =position_dodge(),stat ='identity') +# scale_y_continuous(limits = c(0,100), breaks = c(0,20,40,60,80,100)) +scale_x_continuous('År', guide =guide_axis(n.dodge =2)) +scale_color_gender() +scale_fill_gender() +theme_minimal() +theme_rise() +facet_grid(Årskurs~diskriminerad,labeller =labeller(diskriminerad =label_wrap_gen(16))) ```#### Figur 3Kanske bättre med linje+punkt.```{r}#| fig-width: 10#| fig-height: 6df.viz %>%filter(!diskriminerad %in%c("Ej diskriminerad","Annat")) %>%filter(Årskurs %in%c("Åk 7","Åk 8", "Åk 9")) %>%mutate(Årskurs =droplevels(Årskurs),diskriminerad =droplevels(diskriminerad)) %>%drop_na(diskriminerad) %>%group_by(År,Årskurs,Kön) %>%count(diskriminerad, .drop = F) %>%mutate(Andel =100*n/sum(n)) %>%mutate(diskriminerad =fct_reorder(diskriminerad, desc(n))) %>%ggplot(data = .,aes(x = År, y = Andel, color = Kön, group = Kön)) +geom_point(size =2) +geom_line(linewidth =0.9) +# scale_y_continuous(limits = c(0,100), breaks = c(0,20,40,60,80,100)) +scale_x_continuous('År', guide =guide_axis(n.dodge =2)) +scale_color_gender() +scale_fill_gender() +theme_minimal() +theme_rise() +facet_grid(Årskurs~diskriminerad,labeller =labeller(diskriminerad =label_wrap_gen(16))) ```:::::::### Var känner du dig minst trygg på skolan?:::: column-page-left::: panel-tabset#### Stadium```{r}#| fig-height: 8df.viz %>%drop_na(q13,Kön) %>%filter(!q13 =="Jag känner mig trygg överallt på skolan") %>%ggplot(aes(x = q13, fill = Kön)) +geom_bar(position ="dodge") +# scale_y_continuous(limits = c(0,100), breaks = c(0,20,40,60,80,100)) +scale_x_discrete('', guide =guide_axis(n.dodge =2),labels =~str_wrap(.x, 8)) +scale_color_gender() +scale_fill_gender() +theme_minimal() +theme_rise() +labs(title ="Var känner du dig minst trygg på skolan?",subtitle ="Samtliga årtal",y ="Antal") +facet_wrap(~Stadium,ncol =1)```#### Årskurs```{r}#| fig-height: 8#| fig-width: 10df.viz %>%drop_na(q13,Kön) %>%filter(!q13 =="Jag känner mig trygg överallt på skolan") %>%ggplot(aes(x = q13, fill = Kön)) +geom_bar(position ="dodge") +# scale_y_continuous(limits = c(0,100), breaks = c(0,20,40,60,80,100)) +scale_x_discrete('', guide =guide_axis(n.dodge =3),labels =~str_wrap(.x, 8)) +scale_color_gender() +scale_fill_gender() +theme_minimal() +theme_rise() +labs(title ="Var känner du dig minst trygg på skolan?",subtitle ="Samtliga årtal",y ="Antal") +facet_wrap(~Årskurs) +theme(panel.border =element_rect(colour ="darkgrey", fill =NA))```#### Trygg över tid```{r}#| fig-height: 5df.viz %>%select(q13,År,Stadium,Kön,Årskurs) %>%group_by(År,Stadium,Kön) %>%count(q13, .drop = F) %>%mutate(Andel = n *100/sum(n)) %>%ungroup() %>%filter(q13 =="Jag känner mig trygg överallt på skolan") %>%ggplot(aes(x = År, y = Andel, color = Kön, group = Kön)) +geom_point(size =2) +geom_line(linewidth =0.9) +scale_y_continuous(limits =c(0,100), breaks =c(0,20,40,60,80,100)) +scale_x_continuous('År', guide =guide_axis(n.dodge =2),labels =~str_wrap(.x, 8)) +scale_color_gender() +scale_fill_gender() +theme_minimal() +theme_rise() +labs(title ="Jag känner mig trygg överallt på skolan",y ="Andel") +facet_wrap(~Stadium)```:::::::### Jag känner mig trygg i skolanÄven Skolinspektionen använder denna fråga och båda har fyra svarskategorier. Dock är det inte exakt samma svarskategorier. SI använder *Stämmer helt och hållet, Stämmer ganska bra, Stämmer ganska dåligt, Stämmer inte alls*, medan TTS har *Instämmer helt, 3, 2, Instämmer inte alls*. Därmed är det inte säkert att de är helt jämförbara.:::: column-screen-inset::: panel-tabset#### Samtliga svarskategorier```{r}df.viz %>%select(q6,Stadium,År,Kön) %>%mutate(q6 =recode(q6,"'Vet ej'=NA")) %>%mutate(q6 =factor(q6, levels =c("Instämmer inte alls","2","3","Instämmer helt"))) %>%drop_na(q6) %>%group_by(År,Stadium,Kön) %>%count(q6, .drop = F) %>%mutate(Andel = n *100/sum(n)) %>%ggplot(aes(x = År, y = Andel, color = q6, group = q6)) +geom_point(size =2.2) +geom_line(linewidth =1) +scale_color_manual(values =rev(c("#5C758B","#009CA6", "#B94F70", "#EC5D4F"))) +theme_minimal() +theme_rise() +scale_y_continuous(limits =c(0,100),breaks =c(0,20,40,60,80,100)) +scale_x_continuous('År', guide =guide_axis(n.dodge =2)) +theme(panel.border =element_rect(color ="darkgrey", fill =NA)) +facet_grid(Kön~Stadium) +labs(title ="Jag känner mig trygg i skolan",subtitle ="Samtliga svarskategorier")```#### "Positiva/negativa"```{r}df.viz %>%select(q6,Stadium,År,Kön) %>%mutate(q6 =recode(q6,"'Vet ej'=NA;'2'='Instämmer inte alls';'3'='Instämmer helt'")) %>%mutate(q6 =factor(q6, levels =c("Instämmer inte alls","Instämmer helt"))) %>%drop_na(q6) %>%group_by(År,Stadium,Kön) %>%count(q6, .drop = F) %>%mutate(Andel = n *100/sum(n)) %>%ggplot(aes(x = År, y = Andel, color = q6, group = q6)) +geom_point(size =2.2) +geom_line(linewidth =1) +scale_color_manual(values =rev(c("#5C758B","#EC5D4F"))) +theme_minimal() +theme_rise() +scale_y_continuous(limits =c(0,100),breaks =c(0,20,40,60,80,100)) +scale_x_continuous('År', guide =guide_axis(n.dodge =2)) +theme(panel.border =element_rect(color ="darkgrey", fill =NA)) +facet_grid(Kön~Stadium) +labs(title ="Jag känner mig trygg i skolan",subtitle ="Sammanslagna svarskategorier")```#### Samtliga skola```{r}#| fig-height: 8#| fig-width: 15df.viz %>%select(q6,Skola,År,Kön) %>%mutate(q6 =recode(q6,"'Vet ej'=NA")) %>%mutate(q6 =factor(q6, levels =c("Instämmer inte alls","2","3","Instämmer helt"))) %>%drop_na(q6) %>%group_by(År,Skola,Kön) %>%count(q6, .drop = F) %>%mutate(Andel = n *100/sum(n)) %>%ungroup() %>%mutate(Skola =str_replace(Skola,"skolan","- skolan")) %>%ggplot(aes(x = År, y = Andel, color = q6, group = q6)) +geom_point(size =2.2) +geom_line(linewidth =1) +scale_color_manual('',values =rev(c("#5C758B","#009CA6", "#B94F70", "#EC5D4F"))) +theme_minimal() +theme_rise() +scale_y_continuous(limits =c(0,100),breaks =c(0,20,40,60,80,100)) +scale_x_continuous('År', guide =guide_axis(n.dodge =2)) +theme(panel.border =element_rect(color ="darkgrey", fill =NA),legend.position ="top") +facet_grid(Kön~Skola,labeller =labeller(Skola =label_wrap_gen(4))) +labs(title ="Jag känner mig trygg i skolan",subtitle ="Samtliga svarskategorier")```#### "Positiva/negativa" skola```{r}#| fig-height: 8#| fig-width: 15df.viz %>%select(q6,Skola,År,Kön) %>%mutate(q6 =recode(q6,"'Vet ej'=NA;'2'='Instämmer inte alls';'3'='Instämmer helt'")) %>%mutate(q6 =factor(q6, levels =c("Instämmer inte alls","Instämmer helt"))) %>%drop_na(q6) %>%group_by(År,Skola,Kön) %>%count(q6, .drop = F) %>%mutate(Andel = n *100/sum(n)) %>%ungroup() %>%mutate(Skola =str_replace(Skola,"skolan","- skolan")) %>%ggplot(aes(x = År, y = Andel, color = q6, group = q6)) +geom_point(size =2.2) +geom_line(linewidth =1) +scale_color_manual('',values =rev(c("#5C758B","#EC5D4F"))) +theme_minimal() +theme_rise() +scale_y_continuous(limits =c(0,100),breaks =c(0,20,40,60,80,100)) +scale_x_continuous('År', guide =guide_axis(n.dodge =2)) +theme(panel.border =element_rect(color ="darkgrey", fill =NA),legend.position ="top") +facet_grid(Kön~Skola,labeller =labeller(Skola =label_wrap_gen(4))) +labs(title ="Jag känner mig trygg i skolan",subtitle ="Sammanslagna svarskategorier")```:::::::### Jag trivs i skolan:::: column-screen-inset::: panel-tabset#### Samtliga svarskategorier```{r}df.viz %>%select(q1,Stadium,År,Kön) %>%mutate(q1 =recode(q1,"'Vet ej'=NA")) %>%mutate(q1 =factor(q1, levels =c("Instämmer inte alls","2","3","Instämmer helt"))) %>%drop_na(q1) %>%group_by(År,Stadium,Kön) %>%count(q1, .drop = F) %>%mutate(Andel = n *100/sum(n)) %>%ggplot(aes(x = År, y = Andel, color = q1, group = q1)) +geom_point(size =2.2) +geom_line(linewidth =1) +scale_color_manual(values =rev(c("#5C758B","#009CA6", "#B94F70", "#EC5D4F"))) +theme_minimal() +theme_rise() +scale_y_continuous(limits =c(0,100),breaks =c(0,20,40,60,80,100)) +scale_x_continuous('År', guide =guide_axis(n.dodge =2)) +theme(panel.border =element_rect(color ="darkgrey", fill =NA)) +facet_grid(Kön~Stadium) +labs(title ="Jag trivs i skolan",subtitle ="Samtliga svarskategorier")```#### "Positiva/negativa"```{r}df.viz %>%select(q1,Stadium,År,Kön) %>%mutate(q1 =recode(q1,"'Vet ej'=NA;'2'='Instämmer inte alls';'3'='Instämmer helt'")) %>%mutate(q1 =factor(q1, levels =c("Instämmer inte alls","Instämmer helt"))) %>%drop_na(q1) %>%group_by(År,Stadium,Kön) %>%count(q1, .drop = F) %>%mutate(Andel = n *100/sum(n)) %>%ggplot(aes(x = År, y = Andel, color = q1, group = q1)) +geom_point(size =2.2) +geom_line(linewidth =1) +scale_color_manual(values =rev(c("#5C758B","#EC5D4F"))) +theme_minimal() +theme_rise() +scale_y_continuous(limits =c(0,100),breaks =c(0,20,40,60,80,100)) +scale_x_continuous('År', guide =guide_axis(n.dodge =2)) +theme(panel.border =element_rect(color ="darkgrey", fill =NA)) +facet_grid(Kön~Stadium) +labs(title ="Jag trivs i skolan",subtitle ="Sammanslagna svarskategorier")```#### Samtliga skola```{r}#| fig-height: 8#| fig-width: 15df.viz %>%select(q1,Skola,År,Kön) %>%mutate(q1 =recode(q1,"'Vet ej'=NA")) %>%mutate(q1 =factor(q1, levels =c("Instämmer inte alls","2","3","Instämmer helt"))) %>%drop_na(q1) %>%group_by(År,Skola,Kön) %>%count(q1, .drop = F) %>%mutate(Andel = n *100/sum(n)) %>%ungroup() %>%mutate(Skola =str_replace(Skola,"skolan","- skolan")) %>%ggplot(aes(x = År, y = Andel, color = q1, group = q1)) +geom_point(size =2.2) +geom_line(linewidth =1) +scale_color_manual('',values =rev(c("#5C758B","#009CA6", "#B94F70", "#EC5D4F"))) +theme_minimal() +theme_rise() +scale_y_continuous(limits =c(0,100),breaks =c(0,20,40,60,80,100)) +scale_x_continuous('År', guide =guide_axis(n.dodge =2)) +theme(panel.border =element_rect(color ="darkgrey", fill =NA),legend.position ="top") +facet_grid(Kön~Skola,labeller =labeller(Skola =label_wrap_gen(4))) +labs(title ="Jag trivs i skolan",subtitle ="Samtliga svarskategorier")```#### "Positiva/negativa" skola```{r}#| fig-height: 8#| fig-width: 15df.viz %>%select(q1,Skola,År,Kön) %>%mutate(q1 =recode(q1,"'Vet ej'=NA;'2'='Instämmer inte alls';'3'='Instämmer helt'")) %>%mutate(q1 =factor(q1, levels =c("Instämmer inte alls","Instämmer helt"))) %>%drop_na(q1) %>%group_by(År,Skola,Kön) %>%count(q1, .drop = F) %>%mutate(Andel = n *100/sum(n)) %>%ungroup() %>%mutate(Skola =str_replace(Skola,"skolan","- skolan")) %>%ggplot(aes(x = År, y = Andel, color = q1, group = q1)) +geom_point(size =2.2) +geom_line(linewidth =1) +scale_color_manual('',values =rev(c("#5C758B","#EC5D4F"))) +theme_minimal() +theme_rise() +scale_y_continuous(limits =c(0,100),breaks =c(0,20,40,60,80,100)) +scale_x_continuous('År', guide =guide_axis(n.dodge =2)) +theme(panel.border =element_rect(color ="darkgrey", fill =NA),legend.position ="top") +facet_grid(Kön~Skola,labeller =labeller(Skola =label_wrap_gen(4))) +labs(title ="Jag trivs i skolan",subtitle ="Sammanslagna svarskategorier")```:::::::### Indexvärde TTS```{r}df.viz.index <- df %>%filter(!Stadium =="Förskoleklass") %>%mutate(Kön = car::recode(Kön,"'Annat/Vill ej svara'=NA")) %>%mutate(across(q1:q10, ~ car::recode(.x,"'Instämmer inte alls'=0; 2=1; 3=2; 'Instämmer helt'=3; 'Vet ej'=NA; '<NA>'=NA",as.factor =FALSE))) %>%mutate(q10 =recode(q10,"1=0;2=1;3=1"), as.factor=F) %>%select(all_of(names(df.index)),diskriminerad,Kön,Årskurs,Stadium,År,Skola) %>%mutate(Årskurs =droplevels(Årskurs),Stadium =droplevels(Stadium)) %>%mutate(Stadium =factor(Stadium, levels =c("Lågstadiet","Mellanstadiet","Högstadiet"))) %>%na.omit()df.viz.index$score <-RIestThetas2(df.viz.index %>%select(starts_with("q")), cpu =8)#write_parquet(df.viz.index,"TTSscored.parquet")``````{r}#| column: marginRIlistItemsMargin(df.index)```::: panel-tabset#### Stadium```{r}df.viz.index %>%group_by(År, Stadium, Kön) %>%reframe(Medel =mean(score, na.rm = T), # calculate averages, etcStDev =sd(score, na.rm = T),n =n(),StErr = StDev /sqrt(n),sd.lo = Medel - StDev,sd.hi = Medel + StDev ) %>%mutate(across(where(is.numeric), ~round(.x, 3))) %>%ggplot(aes(x = År, y = Medel, group = Kön, color = Kön)) +# make plot, with area colorgeom_line(linewidth =1) +geom_point(size =2.5) +# geom_line(data = filter(df.plot, Kommun == fokusKommun),# alpha = 0.9, linewidth = 1.2,) +# geom_point(data = filter(df.plot, Kommun == fokusKommun),# alpha = 0.9, size = 3) +geom_ribbon(aes(ymin = sd.lo, ymax = sd.hi, fill = Kön),alpha =0.05, linetype =0 ) +#scale_y_continuous(limits = xlim) +scale_x_continuous(guide =guide_axis(n.dodge =2)) +scale_color_gender() +scale_fill_gender() +labs(title ="Medelvärde över tid",subtitle ="Skuggat fält indikerar en standardavvikelse (~ 68%)") +xlab("Årtal") +theme_minimal() +theme_rise() +theme(panel.spacing =unit(0.7, "cm")) +facet_wrap(~Stadium) +coord_cartesian(ylim =c(-2,4.5))```#### Årskurs```{r}#| fig-height: 7df.viz.index %>%group_by(År, Årskurs, Kön) %>%reframe(Medel =mean(score, na.rm = T), # calculate averages, etcStDev =sd(score, na.rm = T),n =n(),StErr = StDev /sqrt(n),sd.lo = Medel - StDev,sd.hi = Medel + StDev ) %>%mutate(across(where(is.numeric), ~round(.x, 3))) %>%#mutate(Skola = str_replace(Skola,"skolan","- skolan")) %>% ggplot(aes(x = År, y = Medel, group = Kön, color = Kön)) +# make plot, with area colorgeom_line(linewidth =1) +geom_point(size =2.5) +# geom_line(data = filter(df.plot, Kommun == fokusKommun),# alpha = 0.9, linewidth = 1.2,) +# geom_point(data = filter(df.plot, Kommun == fokusKommun),# alpha = 0.9, size = 3) +geom_ribbon(aes(ymin = sd.lo, ymax = sd.hi, fill = Kön),alpha =0.05, linetype =0 ) +#scale_y_continuous(limits = xlim) +scale_x_continuous(guide =guide_axis(n.dodge =2)) +scale_color_gender() +scale_fill_gender() +labs(title ="Medelvärde över tid",subtitle ="Skuggat fält indikerar en standardavvikelse (~ 68%)") +xlab("Årtal") +theme_minimal() +theme_rise() +theme(panel.spacing =unit(0.7, "cm")) +facet_wrap(~Årskurs,nrow =3) +coord_cartesian(ylim =c(-2,4.5))```::::::: column-screen-inset::: panel-tabset#### Alla skolor```{r}#| fig-width: 14#| fig-height: 8df.viz.index %>%group_by(År, Skola, Kön) %>%reframe(Medel =mean(score, na.rm = T), # calculate averages, etcStDev =sd(score, na.rm = T),n =n(),StErr = StDev /sqrt(n),sd.lo = Medel - StDev,sd.hi = Medel + StDev ) %>%mutate(across(where(is.numeric), ~round(.x, 3))) %>%mutate(Skola =str_replace(Skola,"skolan","- skolan")) %>%ggplot(aes(x = År, y = Medel, group = Kön, color = Kön)) +# make plot, with area colorgeom_line(linewidth =1) +geom_point(size =2.5) +# geom_line(data = filter(df.plot, Kommun == fokusKommun),# alpha = 0.9, linewidth = 1.2,) +# geom_point(data = filter(df.plot, Kommun == fokusKommun),# alpha = 0.9, size = 3) +# geom_ribbon(aes(ymin = sd.lo, ymax = sd.hi, fill = Kön),# alpha = 0.05, linetype = 0# ) +#scale_y_continuous(limits = xlim) +scale_x_continuous(guide =guide_axis(n.dodge =2)) +scale_color_gender() +scale_fill_gender() +labs(title ="Medelvärde över tid") +xlab("Årtal") +theme_minimal() +theme_rise() +theme(panel.spacing =unit(0.7, "cm")) +facet_wrap(~Skola,nrow =1,labeller =labeller(Skola =label_wrap_gen(4))) +coord_cartesian(ylim =c(-2,4.5))```#### Högstadie```{r}#| fig-width: 14#| fig-height: 8df.viz.index %>%filter(Stadium =="Högstadiet") %>%group_by(År, Skola, Kön) %>%reframe(Medel =mean(score, na.rm = T), # calculate averages, etcStDev =sd(score, na.rm = T),n =n(),StErr = StDev /sqrt(n),sd.lo = Medel - StDev,sd.hi = Medel + StDev ) %>%mutate(across(where(is.numeric), ~round(.x, 3))) %>%mutate(Skola =str_replace(Skola,"skolan","- skolan")) %>%ggplot(aes(x = År, y = Medel, group = Kön, color = Kön)) +# make plot, with area colorgeom_line(linewidth =1) +geom_point(size =2.5) +# geom_line(data = filter(df.plot, Kommun == fokusKommun),# alpha = 0.9, linewidth = 1.2,) +# geom_point(data = filter(df.plot, Kommun == fokusKommun),# alpha = 0.9, size = 3) +# geom_ribbon(aes(ymin = sd.lo, ymax = sd.hi, fill = Kön),# alpha = 0.05, linetype = 0# ) +#scale_y_continuous(limits = xlim) +scale_x_continuous(guide =guide_axis(n.dodge =2)) +scale_color_gender() +scale_fill_gender() +labs(title ="Medelvärde över tid") +xlab("Årtal") +theme_minimal() +theme_rise() +theme(panel.spacing =unit(0.7, "cm")) +facet_wrap(~Skola,nrow =1,labeller =labeller(Skola =label_wrap_gen(4))) +coord_cartesian(ylim =c(-2,4.5))```#### Mellanstadie```{r}#| fig-width: 14#| fig-height: 8df.viz.index %>%filter(Stadium =="Mellanstadiet") %>%group_by(År, Skola, Kön) %>%reframe(Medel =mean(score, na.rm = T), # calculate averages, etcStDev =sd(score, na.rm = T),n =n(),StErr = StDev /sqrt(n),sd.lo = Medel - StDev,sd.hi = Medel + StDev ) %>%mutate(across(where(is.numeric), ~round(.x, 3))) %>%mutate(Skola =str_replace(Skola,"skolan","- skolan")) %>%ggplot(aes(x = År, y = Medel, group = Kön, color = Kön)) +# make plot, with area colorgeom_line(linewidth =1) +geom_point(size =2.5) +# geom_line(data = filter(df.plot, Kommun == fokusKommun),# alpha = 0.9, linewidth = 1.2,) +# geom_point(data = filter(df.plot, Kommun == fokusKommun),# alpha = 0.9, size = 3) +# geom_ribbon(aes(ymin = sd.lo, ymax = sd.hi, fill = Kön),# alpha = 0.05, linetype = 0# ) +#scale_y_continuous(limits = xlim) +scale_x_continuous(guide =guide_axis(n.dodge =2)) +scale_color_gender() +scale_fill_gender() +labs(title ="Medelvärde över tid") +xlab("Årtal") +theme_minimal() +theme_rise() +theme(panel.spacing =unit(0.7, "cm")) +facet_wrap(~Skola,nrow =1,labeller =labeller(Skola =label_wrap_gen(4))) +coord_cartesian(ylim =c(-2,4.5))```#### Lågstadie```{r}#| fig-width: 14#| fig-height: 8df.viz.index %>%filter(Stadium =="Lågstadiet") %>%group_by(År, Skola, Kön) %>%reframe(Medel =mean(score, na.rm = T), # calculate averages, etcStDev =sd(score, na.rm = T),n =n(),StErr = StDev /sqrt(n),sd.lo = Medel - StDev,sd.hi = Medel + StDev ) %>%mutate(across(where(is.numeric), ~round(.x, 3))) %>%mutate(Skola =str_replace(Skola,"skolan","- skolan")) %>%ggplot(aes(x = År, y = Medel, group = Kön, color = Kön)) +# make plot, with area colorgeom_line(linewidth =1) +geom_point(size =2.5) +# geom_line(data = filter(df.plot, Kommun == fokusKommun),# alpha = 0.9, linewidth = 1.2,) +# geom_point(data = filter(df.plot, Kommun == fokusKommun),# alpha = 0.9, size = 3) +# geom_ribbon(aes(ymin = sd.lo, ymax = sd.hi, fill = Kön),# alpha = 0.05, linetype = 0# ) +#scale_y_continuous(limits = xlim) +scale_x_continuous(guide =guide_axis(n.dodge =2)) +scale_color_gender() +scale_fill_gender() +labs(title ="Medelvärde över tid") +xlab("Årtal") +theme_minimal() +theme_rise() +theme(panel.spacing =unit(0.7, "cm")) +facet_wrap(~Skola,nrow =1,labeller =labeller(Skola =label_wrap_gen(4))) +coord_cartesian(ylim =c(-2,4.5))```:::::::